import { asyncRoutes, constantRoutes } from '@/router';
import { getToken, removeLoginToken, getUser, getUserAdmin, setRoutes, getRoutes, removeRoutes, setBtns, getBtns, setUserRole, getUserRole } from '@/utils/Token';

const state = {
  token: getToken(),
  userInfo: getUser(),
  roleBtns: getBtns(),
  userRole: getUserRole(),
  showSelfInfo: false,
  showPassword: false,
  isAdmin: getUserAdmin(),
  initRoutes: constantRoutes,
  // currentRoutes: constantRoutes.concat(getRoutes())
  currentRoutes: getRoutes()
}

const mutations = {
  SET_TOKEN: (state, token) => {
    state.token = token;
  },
  SET_USER: (state, user) => {
    state.userInfo = user;
  },
  SET_ADMIN: (state, value) => {
    state.isAdmin = value;
  },
  SET_BTNS: (state, btns) => {
    setBtns(btns);
    state.roleBtns = btns;
  },
  SET_USERROLE: (state, role) => {
    setUserRole(role);
    state.userRole = role;
  },
  SET_ROUTES: (state, routes) => {
    setRoutes(routes);
    state.currentRoutes = routes;
  },
  RESET_ROUTES: (state) => {
    setRoutes([]);
    state.currentRoutes = [];
  },
  SHOW_SELFINFO: (state, value) => {
    state.showSelfInfo = value;
  },
  CHANGE_PASSWORD: (state, value) => {
    state.showPassword = value;
  }
}

const actions = {
  // user login
  login({ commit }, data) {
    const { authorization, user } = data;
    commit('SET_TOKEN', authorization);
    commit('SET_USER', user);
    commit('SET_ADMIN', JSON.parse(user).id == 1 || (JSON.parse(user).isAdmin == 1));
  },

  // user logout
  logout({ commit, state, dispatch }) {
    return new Promise((resolve, reject) => {
      commit('SET_TOKEN', '');
      commit('SET_USER', null);
      commit('SET_ADMIN', false);
      removeRoutes();
      removeLoginToken();
      localStorage.removeItem('CurrentUserRoutesModule');
      resolve();
    })
  },

  // remove token
  resetToken({ commit }) {
    return new Promise(resolve => {
      commit('SET_TOKEN', '');
      commit('SET_USER', null);
      commit('SET_ADMIN', false);
      removeLoginToken();
      resolve();
    });
  },

  generateRoutes({ commit }, roles) {
    return new Promise(resolve => {
      let accessedRoutes
      if (roles.includes('admin')) {
        accessedRoutes = asyncRoutes || []
      } else {
        accessedRoutes = filterAsyncRoutes(asyncRoutes, roles)
      }
      commit('SET_ROUTES', accessedRoutes)
      resolve(accessedRoutes)
    })
  }
}

export default {
  namespaced: true,
  state,
  mutations,
  actions
}

/**
 * Use meta.role to determine if the current user has permission
 * @param roles
 * @param route
 */
function hasPermission(roles, route) {
  if (route.meta && route.meta.roles) {
    return roles.some(role => route.meta.roles.includes(role))
  } else {
    return true
  }
}

/**
 * Filter asynchronous routing tables by recursion
 * @param routes asyncRoutes
 * @param roles
 */
export function filterAsyncRoutes(routes, roles) {
  const res = []

  routes.forEach(route => {
    const tmp = { ...route }
    if (hasPermission(roles, tmp)) {
      if (tmp.children) {
        tmp.children = filterAsyncRoutes(tmp.children, roles)
      }
      res.push(tmp)
    }
  })

  return res
}
